

(function() {

	var object = typeof exports != 'undefined' ? exports : self; // #8: web workers
	var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';

	function InvalidCharacterError(message) {
		this.message = message;
	}
	InvalidCharacterError.prototype = new Error;
	InvalidCharacterError.prototype.name = 'InvalidCharacterError';

	// encoder
	// [https://gist.github.com/999166] by [https://github.com/nignag]
	object.btoa || (
		object.btoa = function(input) {
			var str = String(input);
			for(
				// initialize result and counter
				var block, charCode, idx = 0, map = chars, output = '';
				// if the next str index does not exist:
				//   change the mapping table to "="
				//   check if d has no fractional digits
				str.charAt(idx | 0) || (map = '=', idx % 1);
				// "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
				output += map.charAt(63 & block >> 8 - idx % 1 * 8)
			) {
				charCode = str.charCodeAt(idx += 3 / 4);
				if(charCode > 0xFF) {
					throw new InvalidCharacterError("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
				}
				block = block << 8 | charCode;
			}
			return output;
		});

	// decoder
	// [https://gist.github.com/1020396] by [https://github.com/atk]
	object.atob || (
		object.atob = function(input) {
			var str = String(input).replace(/=+$/, '');
			if(str.length % 4 == 1) {
				throw new InvalidCharacterError("'atob' failed: The string to be decoded is not correctly encoded.");
			}
			for(
				// initialize result and counters
				var bc = 0, bs, buffer, idx = 0, output = '';
				// get next character
				buffer = str.charAt(idx++);
				// character found in table? initialize bit storage and add its ascii value;
				~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
					// and if not first of each 4 characters,
					// convert the first 8 bits to one ascii character
					bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
			) {
				// try to find character in table (0-63, not found => -1)
				buffer = chars.indexOf(buffer);
			}
			return output;
		});

}());

var linkTypes = { item: 2, text: 3, map: 4, skill: 6, trait: 7, recipe: 9, skin: 10, outfit: 11 };

/**
 * gw2编码算法
 * @param {Object} 链接类型，地图为map
 * @param {Object} id，可从官方获取
 */
function encodeChatLink(type, id) {
	if(!type) {
		return 'invalid type';
	}
	type = linkTypes[type.trim().toLowerCase()] || 0;
	if(!type) {
		return 'invalid type';
	}

	var data = [];
	while(id > 0) {
		data.push(id & 255);
		id = id >> 8;
	}
	while(data.length < 4 || data.length % 2 != 0) {
		data.push(0);
	}

	if(type == 2) {
		data.unshift(1);
	}
	data.unshift(type);

	// encode data
	var binary = '';
	for(var i = 0; i < data.length; i++) {
		binary += String.fromCharCode(data[i]);
	}
	return '[&' + btoa(binary) + ']';
}

//var code = encodeChatLink('map', 1);
//console.log(code);